﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Globalization;
using System.Drawing;
using System.IO;
using System.ComponentModel.DataAnnotations;
using System.Xml;
using System.Windows.Forms;

namespace NugetPublishWizard.Models
{
    [Serializable]
    public class NugetPackage
    {
        private NugetPackageMetaData _metaData = new NugetPackageMetaData();
        public NugetPackageMetaData MetaData { get { return _metaData; } set { this._metaData = value; } }
        public List<NugetPackageFile> Lib { get; set; }
        public List<NugetPackageFile> Content { get; set; }
        public string ProjectFileName { get; set; }
        public string ActiveConfigurationName { get; set; }
        public List<string> OutputDirectories { get; set; }
        public bool PushPackage { get; set; }
        public bool PublishPackage { get; set; }

        public NugetPackage()
        {
            this.MetaData.Id = string.Empty;
            this._metaData.Language = CultureInfo.GetCultureInfo("en-US");
            this._metaData.Version = new Version(1,0,0,0).ToString();
            this._metaData.Authors = new List<string>();
            this._metaData.Owners = new List<string>();
            this._metaData.Tags = new List<string>();
            this._metaData.Dependencies = new List<NugetDependencie>();
            this.Content = new List<NugetPackageFile>();
            this.Lib = new List<NugetPackageFile>();
            this.OutputDirectories = new List<string>();
        }

        public bool Build(ref string output, ref string filePath)
        {
            // get temp directory
            string path = Path.GetTempPath();
            Guid tempId = Guid.NewGuid();
            path += string.Format(@"{0}\", tempId.ToString());
            Directory.CreateDirectory(path);
            // create nuspec file
            FileInfo nugetSpecFile = new FileInfo(string.Format(@"{0}\Package.nuspec", path));
            CreateNugetspecFile(nugetSpecFile);
            // copy files
            foreach (NugetPackageFile f in this.Content)
            {
                FileInfo file = new FileInfo(string.Format(@"{0}\{1}", path, f.PackageFile));
                if (!file.Directory.Exists)
                    file.Directory.Create();
                f.LocalFile.CopyTo(file.FullName,true);
            }
            foreach (NugetPackageFile f in this.Lib)
            {
                FileInfo file = new FileInfo(string.Format(@"{0}\{1}", path, f.PackageFile));
                if (!file.Directory.Exists)
                    file.Directory.Create();
                f.LocalFile.CopyTo(file.FullName, true);
            }

            // call nuget.exe
            NugetRemote remote = new NugetRemote();
            bool result = remote.Pack(nugetSpecFile.FullName);

            filePath = string.Format(@"{0}\{1}.{2}.nupkg", Environment.CurrentDirectory, this.MetaData.Id, this.MetaData.Version);

            // remove temp directory
            Directory.Delete(path, true);

            if (File.Exists(filePath) && result)
            {
                output = "Package successfuly created";
                return true;
            }
            else
            {
                output = remote.Output[remote.Output.Count - 1];
                return false;
            }
        }

        public static bool Push(string packagePath, string source, string apiKey, ref string output)
        {
            NugetRemote remote = new NugetRemote();
            return remote.Push(packagePath, source, apiKey, ref output);
        }

        public static bool Publish(string id, string version, string source, string apiKey, ref string output)
        {
            NugetRemote remote = new NugetRemote();
            return remote.Publish(id, version, source, apiKey, ref output);
        }

        public static bool Remove(string id, string version, string source, string apiKey, ref string output)
        {
            NugetRemote remote = new NugetRemote();
            return remote.Remove(id, version, source, apiKey, ref output);
        }

        private void CreateNugetspecFile(FileInfo filePath)
        {
            XmlTextWriter writer = new XmlTextWriter(filePath.FullName, Encoding.UTF8);
            writer.Formatting = Formatting.Indented;
            writer.WriteStartDocument();
            writer.WriteStartElement("package");
            writer.WriteStartElement("metadata");

            writer.WriteElementString("id", this.MetaData.Id);
            writer.WriteElementString("version", this.MetaData.Version.ToString());
            if (!string.IsNullOrEmpty(this.MetaData.Title))
                writer.WriteElementString("title", this.MetaData.Title);
            if (!string.IsNullOrEmpty(this.MetaData.Description))
                writer.WriteElementString("description", this.MetaData.Description.Replace("\r\n",""));
            if (this.MetaData.Summary != null)
                writer.WriteElementString("summary", this.MetaData.Summary.Replace("\r\n", ""));
            if (this.MetaData.Language != null)
                writer.WriteElementString("language", this.MetaData.Language.ToString());
            if (!string.IsNullOrEmpty(this.MetaData.ProjectUrl))
                writer.WriteElementString("projectUrl", this.MetaData.ProjectUrl.ToString());
            if (!string.IsNullOrEmpty(this.MetaData.IconUrl))
                writer.WriteElementString("iconUrl", this.MetaData.IconUrl.ToString());
            if (!string.IsNullOrEmpty(this.MetaData.LicenseUrl))
            {
                writer.WriteElementString("licenseUrl", this.MetaData.LicenseUrl.ToString());
                writer.WriteElementString("requireLicenseAcceptance", this.MetaData.RequireLicenseAcceptance.ToString().ToLower());
            }

            if (this.MetaData.Authors != null && this.MetaData.Authors.Count != 0)
            {
                writer.WriteElementString("authors", Helper.ListToString(this.MetaData.Authors, ','));
            }

            if (this.MetaData.Owners != null && this.MetaData.Owners.Count != 0)
            {
                writer.WriteElementString("owners", Helper.ListToString(this.MetaData.Owners, ','));
            }

            if (this.MetaData.Tags != null && this.MetaData.Tags.Count != 0)
            {
                writer.WriteElementString("tags", Helper.ListToString(this.MetaData.Tags, ' '));
            }

            if (this.MetaData.Dependencies.Count != 0)
            {
                writer.WriteStartElement("dependencies");
                foreach (NugetDependencie de in this.MetaData.Dependencies)
                {
                    writer.WriteStartElement("dependency");
                    writer.WriteAttributeString("id", de.Id);
                    if (de.Version != "newest")
                        writer.WriteAttributeString("version", de.Version);
                    writer.WriteEndElement();
                }
                writer.WriteEndElement();
            }

            writer.WriteEndElement();
            writer.WriteEndElement();
            writer.WriteEndDocument();
            writer.Close();
        }

        //private void SaveTemplate(FileInfo filePath)
        //{
        //    XmlTextWriter writer = new XmlTextWriter(filePath.FullName, Encoding.UTF8);
        //    writer.Formatting = Formatting.Indented;
        //    writer.WriteStartDocument();
        //    writer.WriteStartElement("package");
        //    writer.WriteStartElement("metadata");

        //    writer.WriteElementString("id", this.MetaData.Id);
        //    writer.WriteElementString("version", this.MetaData.Version.ToString());
        //    if (!string.IsNullOrEmpty(this.MetaData.Title))
        //        writer.WriteElementString("title", this.MetaData.Title);
        //    if (!string.IsNullOrEmpty(this.MetaData.Description))
        //        writer.WriteElementString("description", this.MetaData.Description.Replace("\r\n", ""));
        //    if (this.MetaData.Summary != null)
        //        writer.WriteElementString("summary", this.MetaData.Summary.Replace("\r\n", ""));
        //    if (this.MetaData.Language != null)
        //        writer.WriteElementString("language", this.MetaData.Language.ToString());
        //    if (!string.IsNullOrEmpty(this.MetaData.ProjectUrl))
        //        writer.WriteElementString("projectUrl", this.MetaData.ProjectUrl.ToString());
        //    if (!string.IsNullOrEmpty(this.MetaData.IconUrl))
        //        writer.WriteElementString("iconUrl", this.MetaData.IconUrl.ToString());
        //    if (!string.IsNullOrEmpty(this.MetaData.LicenseUrl))
        //    {
        //        writer.WriteElementString("licenseUrl", this.MetaData.LicenseUrl.ToString());
        //        writer.WriteElementString("requireLicenseAcceptance", this.MetaData.RequireLicenseAcceptance.ToString().ToLower());
        //    }

        //    if (this.MetaData.Authors != null && this.MetaData.Authors.Count != 0)
        //    {
        //        writer.WriteElementString("authors", Helper.ListToString(this.MetaData.Authors, ','));
        //    }

        //    if (this.MetaData.Owners != null && this.MetaData.Owners.Count != 0)
        //    {
        //        writer.WriteElementString("owners", Helper.ListToString(this.MetaData.Owners, ','));
        //    }

        //    if (this.MetaData.Tags != null && this.MetaData.Tags.Count != 0)
        //    {
        //        writer.WriteElementString("tags", Helper.ListToString(this.MetaData.Tags, ' '));
        //    }

        //    if (this.MetaData.Dependencies.Count != 0)
        //    {
        //        writer.WriteStartElement("dependencies");
        //        foreach (NugetDependencie de in this.MetaData.Dependencies)
        //        {
        //            writer.WriteStartElement("dependency");
        //            writer.WriteAttributeString("id", de.Id);
        //            if (de.Version != "newest")
        //                writer.WriteAttributeString("version", de.Version);
        //            writer.WriteEndElement();
        //        }
        //        writer.WriteEndElement();
        //    }

        //    writer.WriteEndElement();
        //    writer.WriteEndElement();
        //    writer.WriteEndDocument();
        //    writer.Close();
        //}

        public override string ToString()
        {
            return string.Format("{0} ({1})", this.MetaData.Id, this.MetaData.Version.ToString());
        }

        public string GetBuildSummary()
        {
            StringBuilder result = new StringBuilder(this.MetaData.GetBuildSummary());

            if (this.Content.Count != 0)
            {
                result.AppendLine();
                result.AppendLine("Content");
                result.AppendLine("--------------------------------------------------------------------");
                foreach (NugetPackageFile file in this.Content)
                {
                    result.AppendLine(file.PackageFile);
                }
                result.AppendLine("--------------------------------------------------------------------");
            }

            if (this.Lib.Count != 0)
            {
                result.AppendLine();
                result.AppendLine("Lib");
                result.AppendLine("--------------------------------------------------------------------");
                foreach (NugetPackageFile file in this.Lib)
                {
                    result.AppendLine(file.PackageFile);
                }
                result.AppendLine("--------------------------------------------------------------------");
            }

            result.AppendLine();
            result.AppendLine("Output");
            result.AppendLine("--------------------------------------------------------------------");
            foreach (string dir in this.OutputDirectories)
            {
                result.AppendLine(dir);
            }
            result.AppendLine("--------------------------------------------------------------------");

            return result.ToString();
        }
    }
}
